/*
 * @Author: OreoWang
 * @Email: ihc523@163.com
 * @Date: 2022-03-22 21:50:54
 * @LastEditors: OreoWang
 * @LastEditTime: 2022-07-15 09:30:18
 * @Description: 
 */

import { Node, Component, Director, director, game, _decorator } from "cc";
import { EDITOR } from "cc/env";
const { ccclass } = _decorator;
import * as bt from "../main";
import { BehaviorStatus } from "../main";
const logger = console;

@ccclass("BehaviorManager")
export default class BehaviorManager extends Component {
    running: Set<bt.IBehaviorTree> = new Set();
    suspend: Set<bt.IBehaviorTree> = new Set();

    deltaTime = 0;
    ticks = 0;

    protected static _instance: BehaviorManager = null;

    static getInstance() {
        if (!BehaviorManager._instance) {
            let node = new Node("[BehaviorManager]");
            let component = node.addComponent(BehaviorManager);
            BehaviorManager._instance = component;
            if (EDITOR) {
                let scene = director.getScene();
                if(!scene){
                    console.error("BehaviorManager 由 BehaviorTree 自动挂载，请勿手动调用。")
                    node.destroy();
                    return;
                }
                scene.addChild(node);
                director.once(Director.EVENT_BEFORE_SCENE_LAUNCH, ()=>{
                    if(BehaviorManager._instance == component){
                        BehaviorManager._instance = null;
                    }
                })
            }
            else{
                game.addPersistRootNode(node);
            }
        }
        return BehaviorManager._instance;
    }

    constructor() {
        super();
        this.deltaTime = 0
        this.ticks = 0
    }

    addBehavior(context) {
        if (context.startWhenEnabled) {
            this.resumeBehavior(context);
        }
        else {
            this.pauseBehavior(context);
        }
    }
    removeBehavior(context: bt.IBehaviorTree) {
        if (this.running.has(context)) {
            this.running.delete(context);
        }
        if (this.suspend.has(context)) {
            this.suspend.delete(context);
        }
    }
    runBehavior(context: bt.IBehaviorTree) {
        this.addBehavior(context);
    }
    pauseBehavior(context: bt.IBehaviorTree) {
        if (!this.suspend.has(context)) {
            context.onPause();
            this.suspend.add(context);
        }
        if (this.running.has(context)) {
            this.running.delete(context);
        }
    }
    resumeBehavior(context: bt.IBehaviorTree) {
        if (!this.running.has(context)) {
            context.onResume();
            this.running.add(context);
        }
        if (this.suspend.has(context)) {
            this.suspend.delete(context);
        }
    }
    stopBehavior(context: bt.IBehaviorTree) {
        if (this.running.has(context)) {
            context.onStop();
            this.running.delete(context);
        }
        if (!this.suspend.has(context)) {
            this.suspend.add(context);
        }
    }

    /**
     * 更新状态
     * @param {*} delta 上一次tick时间间隔
     */
    tick(delta) {
        this.deltaTime += delta
        this.ticks += 1

        this.running.forEach(context => {
            const status = context.onTick(delta);
            if (status != BehaviorStatus.Running) {
                if (context.restartWhenComplete) {
                    context.onRestart();
                }
                else {
                    context.onFinished();
                    this.stopBehavior(context);
                }
            }
        })
    }

    update(delta: number) {
        this.tick(delta);
    }

    onEnable() {
        this.suspend.forEach(context => {
            if (context.isSuspended) {
                this.resumeBehavior(context);
            }
        })
    }
    onDisable() {
        this.running.forEach(context => {
            if (context.pauseWhenDisabled) {
                this.pauseBehavior(context);
            }
        })
    }
}